package com.vipboot.platform.system.crud.service.rbac;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vipboot.framework.core.constant.Const;
import com.vipboot.framework.core.exception.ServiceException;
import com.vipboot.framework.core.optionselect.OptionSelect;
import com.vipboot.framework.core.optionselect.OptionSelectUtil;
import com.vipboot.framework.core.util.MapStructUtil;
import com.vipboot.framework.core.util.StringUtil;
import com.vipboot.framework.mybatisplus.core.page.PageData;
import com.vipboot.framework.mybatisplus.core.page.PageQuery;
import com.vipboot.framework.mybatisplus.database.DataBaseHelper;
import com.vipboot.platform.system.crud.dao.SysDeptDao;
import com.vipboot.platform.system.crud.dao.SysPostDao;
import com.vipboot.platform.system.crud.dao.SysUserPostDao;
import com.vipboot.platform.system.domain.bo.SysPostBo;
import com.vipboot.platform.system.domain.entity.SysDept;
import com.vipboot.platform.system.domain.entity.SysPost;
import com.vipboot.platform.system.domain.entity.SysUserPost;
import com.vipboot.platform.system.domain.vo.SysPostVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class SysPostService {
    private final SysPostDao sysPostDao;
    private final SysUserPostDao sysUserPostDao;
    private final SysDeptDao sysDeptDao;

    private LambdaQueryWrapper<SysPost> buildQueryWrapper(SysPostBo bo) {
        LambdaQueryWrapper<SysPost> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPost::getDeleteFlag, Const.StatusNormal);
        wrapper.like(StringUtil.isNotBlank(bo.getPostCode()), SysPost::getPostCode, bo.getPostCode())
                .like(StringUtil.isNotBlank(bo.getPostCategory()), SysPost::getPostCategory, bo.getPostCategory())
                .like(StringUtil.isNotBlank(bo.getPostName()), SysPost::getPostName, bo.getPostName())
                .eq(StringUtil.isNotBlank(bo.getStatus()), SysPost::getStatus, bo.getStatus())
                .orderByAsc(SysPost::getSortNum);
//        if (ObjectUtil.isNotNull(bo.getDeptId())) {
//            //优先单部门搜索
//            wrapper.eq(SysPost::getDeptId, bo.getDeptId());
//        } else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) {
//            //部门树搜索
//            wrapper.and(x -> {
//                List<Long> deptIds = sysDeptDao.list(new LambdaQueryWrapper<SysDept>()
//                                .select(SysDept::getDeptId)
//                                .apply(DataBaseHelper.findInSet(bo.getBelongDeptId(), "ancestors")))
//                        .stream()
//                        .map(SysDept::getDeptId)
//                        .collect(Collectors.toList());
//                deptIds.add(bo.getBelongDeptId());
//                x.in(SysPost::getDeptId, deptIds);
//            });
//        }
        return wrapper;
    }

    public PageData<SysPostVo> page(SysPostBo bo, PageQuery pageQuery) {
        Page<SysPostVo> page = sysPostDao.getBaseMapper().selectPagePostList(pageQuery.build(),
                buildQueryWrapper(bo));
        return PageData.build(page);
    }

    public boolean save(SysPostBo bo) {
        if (this.checkExistPostName(bo)) {
            throw new ServiceException("新增岗位'" + bo.getPostName() + "'失败，岗位名称已存在");
        }
        if (this.checkExistPostCode(bo)) {
            throw new ServiceException("新增岗位'" + bo.getPostCode() + "'失败，岗位编码已存在");
        }
        SysPost entity = MapStructUtil.convert(bo, SysPost.class);
        return sysPostDao.save(entity);
    }

    public boolean update(SysPostBo bo) {
        if (this.checkExistPostName(bo)) {
            throw new ServiceException("修改岗位'" + bo.getPostName() + "'失败，岗位名称已存在");
        }
        if (this.checkExistPostCode(bo)) {
            throw new ServiceException("修改岗位'" + bo.getPostCode() + "'失败，岗位编码已存在");
        }
        // 禁用状态
        if (ObjectUtil.equals(bo.getStatus(), Const.StatusDisable)
                && this.checkPostHasUserByPostId(bo.getPostId())) {
            throw new ServiceException("该岗位包含已分配用户,不允许禁用");
        }
        SysPost entity = MapStructUtil.convert(bo, SysPost.class);
        return sysPostDao.updateById(entity);
    }

    //    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Long id) {
        Assert.notNull(id, "主键不能为空");

        if (this.checkPostHasUserByPostId(id)) {
            SysPost entity = sysPostDao.getById(id);
            throw new ServiceException(String.format("%1$s 岗位已分配用户,不能删除!", entity.getPostName()));
        }
        return sysPostDao.removeById(id);
    }

    /**
     * 通过部门 ID查询岗位列表
     *
     * @param deptId 部门ID
     * @return 岗位选择列表信息
     */
    public List<OptionSelect<Long>> listOptionSelectByDeptId(Long deptId) {
        LambdaQueryWrapper<SysPost> lqw = Wrappers.lambdaQuery();
        lqw.select(SysPost::getPostId, SysPost::getPostName, SysPost::getPostCode);
        lqw.eq(SysPost::getStatus, Const.StatusNormal);
//        lqw.eq(SysPost::getDeptId, deptId);
        lqw.orderByAsc(SysPost::getSortNum);

        List<SysPostVo> list = sysPostDao.listVo(lqw, SysPostVo.class);
        return OptionSelectUtil.build(list, (item, option) -> {
            option.setId(item.getPostId());
            option.setValue(item.getPostId());
            option.setLabel(item.getPostName());
        });
    }


    private boolean checkExistPostName(SysPostBo bo) {
        LambdaQueryWrapper<SysPost> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysPost::getPostName, bo.getPostName());
        lqw.ne(ObjectUtil.isNotNull(bo.getPostId()), SysPost::getPostId, bo.getPostId());
        return sysPostDao.exists(lqw);
    }

    private boolean checkExistPostCode(SysPostBo bo) {
        LambdaQueryWrapper<SysPost> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysPost::getPostCode, bo.getPostCode());
        lqw.ne(ObjectUtil.isNotNull(bo.getPostId()), SysPost::getPostId, bo.getPostId());
        return sysPostDao.exists(lqw);
    }

    /**
     * 检验岗位是否存在用户
     *
     * @param postId 岗位ID
     */
    private boolean checkPostHasUserByPostId(Long postId) {
        Assert.notNull(postId, "岗位ID不能为空");
        LambdaQueryWrapper<SysUserPost> lqw = Wrappers.lambdaQuery();
        lqw.select(SysUserPost::getUserId);
        lqw.eq(SysUserPost::getPostId, postId);
        return sysUserPostDao.count(lqw) > 0;
    }

}
